//    Copyright (C) Kherty.  All rights reserved.
#region

using System;
using System.Windows.Documents;
using System.Windows.Input;

#endregion

namespace OpenLS.Spreadsheet.UI.Internals
{
    internal static class CellTextEditorSelection
    {
        internal static void RegisterClassHandlers(Type controlType)
        {
            CanExecuteRoutedEventHandler canExecuteRoutedEventHandler = onQueryStatusCaretNavigation;
            CanExecuteRoutedEventHandler handler3 = onQueryStatusKeyboardSelection;

            CommandHelpers.RegisterCommandHandler(controlType, EditingCommands.MoveRightByCharacter,
                                                  onMoveRightByCharacter, canExecuteRoutedEventHandler, Key.Right);
            CommandHelpers.RegisterCommandHandler(controlType, EditingCommands.MoveLeftByCharacter,
                                                  onMoveLeftByCharacter, canExecuteRoutedEventHandler, Key.Left);
            CommandHelpers.RegisterCommandHandler(controlType, EditingCommands.MoveDownByLine,
                                                  onMoveUpDown, canExecuteRoutedEventHandler, Key.Down);
            CommandHelpers.RegisterCommandHandler(controlType, EditingCommands.MoveUpByLine,
                                                  onMoveUpDown, canExecuteRoutedEventHandler, Key.Up);
            CommandHelpers.RegisterCommandHandler(controlType, EditingCommands.MoveToLineStart, onMoveToLineStart,
                                                  canExecuteRoutedEventHandler, Key.Home);
            CommandHelpers.RegisterCommandHandler(controlType, EditingCommands.MoveToLineEnd, onMoveToLineEnd,
                                                  canExecuteRoutedEventHandler, Key.End);
            CommandHelpers.RegisterCommandHandler(controlType, EditingCommands.SelectToLineStart, onSelectToLineStart,
                                                  canExecuteRoutedEventHandler, Key.Home, ModifierKeys.Shift);
            CommandManager.RegisterClassInputBinding(controlType,
                                            new InputBinding(EditingCommands.SelectToLineStart, new KeyGesture(Key.Left, ModifierKeys.Control)));
            CommandManager.RegisterClassInputBinding(controlType,
                                            new InputBinding(EditingCommands.SelectToLineEnd, new KeyGesture(Key.Right, ModifierKeys.Control)));

            CommandHelpers.RegisterCommandHandler(controlType, EditingCommands.SelectToLineEnd, onSelectToLineEnd,
                                                  canExecuteRoutedEventHandler, Key.End, ModifierKeys.Shift);
            CommandHelpers.RegisterCommandHandler(controlType, EditingCommands.SelectLeftByCharacter,
                                                  onSelectLeftByCharacter, handler3, Key.Left, ModifierKeys.Shift);
            CommandHelpers.RegisterCommandHandler(controlType, EditingCommands.SelectRightByCharacter,
                                                  onSelectRightByCharacter, handler3, Key.Right, ModifierKeys.Shift);
        }

        private static void onMoveUpDown(object sender, ExecutedRoutedEventArgs e)
        {
            e.Handled = true;
        }


        private static void onSelectToLineStart(object sender, ExecutedRoutedEventArgs e)
        {
            select(sender, e, tb => tb.GetLineStart(tb.Source.SelectionIndex));
        }

        private static void onSelectToLineEnd(object sender, ExecutedRoutedEventArgs e)
        {
            select(sender, e, tb => tb.GetLineEnd(tb.Source.SelectionIndex));
        }

        private static void onMoveToLineStart(object sender, ExecutedRoutedEventArgs e)
        {
            move(sender, e, tb => tb.GetLineStart(tb.Source.SelectionIndex));
        }

        private static void onMoveToLineEnd(object sender, ExecutedRoutedEventArgs e)
        {
            move(sender, e, tb => tb.GetLineEnd(tb.Source.SelectionIndex));
        }

        private static void move(object sender, ExecutedRoutedEventArgs e, Func<CellTextBox, int> fn)
        {
            var tb = (CellTextBox) sender;
            tb.Source.Move(fn(tb));
            e.Handled = true;
        }

        private static void move(object sender, ExecutedRoutedEventArgs e, Func<CellTextSource, int> fn)
        {
            var tb = (CellTextBox) sender;
            tb.Source.Move(fn(tb.Source));
            e.Handled = true;
        }

        private static void select(object sender, ExecutedRoutedEventArgs e, Func<CellTextSource, int> fn)
        {
            var tb = (CellTextBox) sender;
            tb.Source.Select(fn(tb.Source));
            e.Handled = true;
        }

        private static void select(object sender, ExecutedRoutedEventArgs e, Func<CellTextBox, int> fn)
        {
            var tb = (CellTextBox) sender;
            tb.Source.Select(fn(tb));
            e.Handled = true;
        }

        private static void onSelectLeftByCharacter(object sender, ExecutedRoutedEventArgs e)
        {
            select(sender, e, ss => ss.OtherIndex - 1);
        }

        private static void onSelectRightByCharacter(object sender, ExecutedRoutedEventArgs e)
        {
            select(sender, e, ss => ss.OtherIndex + 1);
        }

        private static void onQueryStatusKeyboardSelection(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
            e.Handled = true;
        }

        private static void onMoveLeftByCharacter(object sender, ExecutedRoutedEventArgs e)
        {
            move(sender, e, ss => ss.MinIndex - 1);
        }

        private static void onQueryStatusCaretNavigation(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
            e.Handled = true;
        }

        private static void onMoveRightByCharacter(object sender, ExecutedRoutedEventArgs e)
        {
            move(sender, e, ss => ss.MaxIndex + 1);
        }
    }
}